home *** CD-ROM | disk | FTP | other *** search
- #define REF_VERS 0
-
- /******************************************************************************
-
- MODULE
- DYN.c
-
- DESCRIPTION
- Simple Dynamic Strings in "C"
-
- NOTES
- * this file contains 2 implementations:
- one is using bigger base variables (12bytes) and is a little bit faster
- the other is using smaller base variables (4bytes) and is a little bit slower
- (speed is not tested ...)
- * to keep codesize small and for debugging purposes
- (only one function to modify) DynCpy & DynCat are
- using DynIns, so the functions DynCpy and DynCat are
- much slower than necessary.
-
- BUGS
- none known
-
- TODO
- tell me
-
- EXAMPLES
-
- SEE ALSO
-
- HISTORY
- 15-09-94 b_noll created
- 28-09-94 b_noll enhanced !REF_VERS (REF_VERS is going away)
-
- ******************************************************************************/
-
-
- /**************************************
- Includes
- **************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include <assert.h>
-
- #ifdef AMIGA
- #include <clib/exec_protos.h>
- extern APTR SysBase;
- #include <pragmas/exec_pragmas.h>
- #endif
-
- //#undef DYNSTR_MACROS
- #ifndef DYN_H
- #include "DYN.h"
- #endif /* DYN_H */
-
- /**************************************
- Internal Defines & Structures
- **************************************/
-
- #ifndef STREAM
- #define STREAM void *
- #endif
-
- #undef Prototype
- #define Prototype extern
-
- #define STRLEN 32 /* each dynamic string is sized ((STRLEN+strlen()-1)/STRLEN)*STRLEN ... */
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #define BOOL int
- #endif
-
- #define BRA_ do{
- #define KET_ }while(0)
-
- /**************************************
- Implementation
- **************************************/
-
- #if REF_VERS /* ******************************************* */
-
- struct _DSTR {
- int Size;
- int Length;
- char *Str;
- }; /* struct _DSTR */
- #define DSTR struct _DSTR
-
- DSTR _EmptyDyn = {0,0,NULL};
-
- void DynInit (DSTR *pstr) {
- *pstr = _EmptyDyn;
- } /* DynInit */
-
- void DynClear (DSTR *pstr) {
- if (DynValue(pstr))
- free (DynValue(pstr));
- DynInit(pstr);
- } /* DynClear */
-
- void DynReset (DSTR *pstr) {
- if (DynValue (pstr))
- pstr->Length = strlen(DynValue(pstr));
- else
- pstr->Length = pstr->Size = 0;
- } /* DynReset */
-
- void DynErase (DSTR *pstr) {
- if (DynValue (pstr))
- *DynValue(pstr) = 0;
- DynReset(pstr);
- } /* DynErase */
-
- char *DynValue (DSTR *pstr) {
- return pstr->Str;
- } /* DynValue */
-
- int DynSize (DSTR *pstr) {
- return pstr->Size;
- } /* DynSize */
-
- int DynLen (DSTR *pstr) {
- return pstr->Length;
- } /* DynLen */
-
- BOOL DynCpy (DSTR *pstr, const char *src) {
- DynClear(pstr);
- DynCat (pstr, src);
- } /* DynCpy */
-
- BOOL DynCat (DSTR *pstr, const char *src) {
- return DynIns (pstr, src, pstr->Length);
- } /* DynCat */
-
- BOOL DynDel (DSTR *pstr, int pos, int chars) {
- /* ---- Empty? or nothing to Delete */
- if (!pstr->Str || (pstr->Length < pos) || !chars)
- return TRUE;
-
- /* ---- End Truncated? */
- if (pstr->Length < pos + chars) {
- pstr->Length = pos;
- pstr->Str[pos] = 0;
- return TRUE;
- } /* if */
-
- /* ---- Midth Deleted? */
- memcpy (pstr->Str + pos, pstr->Str + pos + chars, pstr->Length + 1 - (chars + pos));
- pstr->Length -= chars;
- return TRUE;
- } /* DynDel */
-
- BOOL DynIns (DSTR *pstr, const char *src, int pos) {
- int slen, tlen;
- char *inter;
- assert (pstr != NULL);
-
- /* ---- make sure we have consistent data */
- if (!pstr->Str)
- pstr->Length = pstr->Size = 0;
-
- /* ---- Empty append? */
- if (!src)
- return TRUE;
- slen = strlen (src);
- if (!slen)
- return TRUE;
-
- /* ---- Fits into old String? */
- if (slen + pstr->Length < pstr->Size) {
- strins (pstr->Str + pos, src); /* DIFF1_2_Cat */
- pstr->Length += len;
- return TRUE;
- } /* if */
-
- /* ---- New Mem needed */
- if (!(inter = malloc (tlen = (STRLEN * (1 + pstr->Length + slen + STRLEN - 1)/STRLEN ))))
- return FALSE;
-
- strcpy (inter, pstr->Str);
- free (pstr->Str);
- strins (inter + pos, src); /* DIFF2_2_Cat */
-
- pstr->Length += slen;
- pstr->Size = tlen;
- pstr->Str = inter;
- return TRUE;
- } /* DynIns */
-
-
- #endif /* ************************************************** */
-
- /*
- #undef DynInit
- #undef DynClear
- #undef DynDelete
- #undef DynReset
- #undef DynErase
- #undef DynLen
- #undef DynSize
- #undef DynValue
- */
-
- #define DB(pstr) (*pstr)
-
-
- /* ---- Return the contents of a DSTR */
- #ifndef DynValue
- Prototype char *DynValue (DSTR *pstr);
- char *DynValue (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- return DB(pstr)->Str;
- return "";
- } /* DynValue */
- #define DynValue(pstr) ((*(pstr))? ((*(pstr))->Str): "")
- #endif
-
-
- /* ---- Return the sizeof() of a DSTR */
- #ifndef DynSize
- Prototype int DynSize (DSTR *pstr);
- int DynSize (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- return DB(pstr)->Size;
- return 0;
- } /* DynSize */
- #define DynSize(pstr) ((*(pstr))? ((*(pstr))->Size): 0)
- #endif
-
-
- /* ---- Return the strlen() of a DSTR */
- #ifndef DynLen
- Prototype int DynLen (DSTR *pstr);
- int DynLen (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- return DB(pstr)->Length;
- return 0;
- } /* DynLen */
- #define DynLen(pstr) ((*(pstr))? ((*(pstr))->Length): 0)
- #endif
-
-
- /* ---- Initialize a DSTR */
- #ifndef DynInit
- Prototype void DynInit (DSTR *pstr);
- void DynInit (DSTR *pstr) {
- assert (pstr != NULL);
- *pstr = EmptyDyn;
- } /* DynInit */
- #define DynInit(pstr) *(pstr) = EmptyDyn
- #endif
-
-
- /* ---- Reset a DSR to initialisation-state */
- #ifndef DynClear
- Prototype void DynClear (DSTR *pstr);
- void DynClear (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- free (DB(pstr));
- DynInit(pstr);
- } /* DynClear */
- #define DynClear(pstr) BRA_ DSTR d; if ((d = *(pstr))) free(d); *(pstr) = EmptyDyn; KET_
- #endif
-
-
- /* ---- Delete a DSTR - make in uninitlialized */
- #ifndef DynDelete
- Prototype void DynDelete (DSTR *pstr);
- void DynDelete (DSTR *pstr) {
- assert (pstr != NULL);
- DynClear (pstr);
- } /* DynDelete */
- #define DynDelete(pstr) DynClear(pstr)
- #endif
-
-
- /* ---- Make sure a DSTR is consistent */
- #ifndef DynReset
- Prototype void DynReset (DSTR *pstr);
- void DynReset (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- DB(pstr)->Length = strlen (DB(pstr)->Str);
- } /* DynReset */
- #define DynReset(pstr) BRA_ DSTR d; if ((d = *(pstr))) d->Length = strlen(d->Str); KET_
- #endif
-
-
- /* ---- Set the contents of a DSTR to "" and keep the DSTR consistent */
- #ifndef DynErase
- Prototype void DynErase (DSTR *pstr);
- void DynErase (DSTR *pstr) {
- assert (pstr != NULL);
- if (DB(pstr))
- DB(pstr)->Length = DB(pstr)->Str[0] = 0;
- } /* DynErase */
- #define DynErase(pstr) BRA_ DSTR d; if ((d = *(pstr))) d->Length = d->Str[0] = 0; KET_
- #endif
-
-
- /* ---- Delete text inside a DSTR */
- Prototype BOOL DynDel (DSTR *pstr, int pos, int chars);
- BOOL DynDel (DSTR *pstr, int pos, int chars) {
- struct _DSTR *dstr;
-
- assert (pstr != NULL);
- dstr = DB(pstr);
- /* ---- Empty? or nothing to Delete */
- if (!(dstr = DB(pstr)) || (dstr->Length < pos) || !chars)
- return TRUE;
-
- /* ---- End Truncated? */
- if (dstr->Length < pos + chars) {
- dstr->Length = pos;
- dstr->Str[pos] = 0;
- return TRUE;
- } /* if */
-
- /* ---- Midth Deleted? */
- memcpy (dstr->Str + pos, dstr->Str + pos + chars, dstr->Length + 1 - (chars + pos));
- dstr->Length -= chars;
- return TRUE;
- } /* DynDel */
-
-
- /* ---- Make sure a DSTR is at least big enough to keep a certain amount of memory */
- Prototype BOOL DynExpand (DSTR *pstr, int max);
- BOOL DynExpand (DSTR *pstr, int max) {
- DSTR new;
- assert (pstr != NULL);
-
- /* ---- no more heap needed? */
- if (DB(pstr) && (DynSize(pstr) > max))
- return TRUE;
-
- /* ---- make size block aligned */
- max = STRLEN * ((max + STRLEN - 1) / STRLEN);
-
- /* ---- New Mem needed */
- if (!(new = malloc (sizeof (*new) + max)))
- return FALSE;
-
- /* ---- init the new str */
- new->Size = max;
- new->Length = 0;
- new->Str[0] = 0;
-
- /* ---- get the old string's data and release it */
- if (DB(pstr)) {
- new->Length = DB(pstr)->Length;
- strcpy (new->Str, DB(pstr)->Str);
- free (DB(pstr));
- } /* if */
- *pstr = new;
-
- return TRUE;
- } /* DynExpand */
-
-
- /* ---- Insert text of a certain length into a DSTR */
- static BOOL _DynLIns (DSTR *pstr, const char *src, int pos, int slen) {
- int use, len;
- struct _DSTR *dstr;
- assert (pstr != NULL);
-
- /* ---- Empty append? */
- if (!src)
- return TRUE;
-
- /* ---- make sure we have at least partly consistent data */
- if (!(dstr = DB(pstr)))
- use = len = 0;
- else {
- use = dstr->Length;
- len = dstr->Size;
- } /* if */
-
- /* ---- what shall happen, if pos>use? */
- /* if (pos > use) return FALSE; */
- if (pos > use) pos = use;
-
- slen = strlen (src);
- /* ---- isn't it better o make sure *pstr!=NULL - remove the next line! */
- /* if (!slen) return TRUE; */
-
- /* ---- Fits into old String? */
- /* New Mem needed and got it? */
- if ((slen + use >= len) && !DynExpand (pstr, use + slen))
- return FALSE;
- dstr = DB(pstr);
-
- /* strins (dstr->Str + pos, src); /* this is the only DIFF_2_Cat */
- memmove(dstr->Str + pos + slen, dstr->Str + pos, dstr->Length + 1 - pos);
- memmove(dstr->Str + pos, src, slen);
- dstr->Length += slen;
-
- return TRUE;
- } /* _DynLIns */
-
-
- /* ---- Insert text into a DSTR */
- Prototype BOOL DynIns (DSTR *pstr, const char *src, int pos);
- BOOL DynIns (DSTR *pstr, const char *src, int pos) {
- assert (pstr != NULL);
- return _DynLIns (pstr, src, pos, src? strlen (src): 0);
- } /* DynIns */
-
-
- /* ---- Append text to a DSTR */
- Prototype BOOL DynCat (DSTR *pstr, const char *src);
- BOOL DynCat (DSTR *pstr, const char *src) {
- // return _DynLIns (pstr, src, DynLen(pstr), src? strlen (src): 0);
- int slen;
- assert (pstr != NULL);
- if (src && DynExpand(pstr, slen = strlen(src) + DynLen(pstr))) {
- strcat (DynValue(pstr) + DynLen(pstr), src);
- DB(pstr)->Length = slen;
- return TRUE;
- } /* if */
- return FALSE;
- } /* DynCat */
-
-
- /* ---- Replace the contents of a DSTR */
- Prototype BOOL DynCpy (DSTR *pstr, const char *src);
- BOOL DynCpy (DSTR *pstr, const char *src) {
- assert (pstr != NULL);
- DynErase (pstr);
- return DynCat (pstr, src);
- } /* DynCpy */
-
-
- /* The DynD* functions are a little bit faster when copying data between
- ** 2 DSTRs that the way via DynValue and the normal Dyn* functions */
-
-
- /* ---- Insert text into a DSTR from a DSTR */
- Prototype BOOL DynDIns (DSTR *pstr, DSTR *src, int pos);
- BOOL DynDIns (DSTR *pstr, DSTR *src, int pos) {
- assert (pstr != NULL);
- return _DynLIns (pstr, DynValue(src), pos, DynLen(src));
- } /* DynDIns */
-
-
- /* ---- Append text to a DSTR from a DSTR */
- Prototype BOOL DynDCat (DSTR *pstr, DSTR *src);
- BOOL DynDCat (DSTR *pstr, DSTR *src) {
- assert (pstr != NULL);
- return _DynLIns (pstr, DynValue(src), DynLen(pstr), DynLen(src));
- } /* DynDCat */
-
-
- /* ---- Replace the contents of a DSTR from a DSTR */
- Prototype BOOL DynDCpy (DSTR *pstr, DSTR *src);
- BOOL DynDCpy (DSTR *pstr, DSTR *src) {
- assert (pstr != NULL);
- DynErase (pstr);
- return DynDCat (pstr, src);
- } /* DynDCpy */
-
-
- /* ---- _TRY_ to replace the value of a STR */
- /* the use of this function is recommended, if the */
- /* old value of a DSTR shall stay valid in the case */
- /* there is not enough heap to hold the new value */
- /* the price for this security, is less speed */
- Prototype BOOL DynSCpy (DSTR *pstr, const char *src);
- BOOL DynSCpy (DSTR *pstr, const char *src) {
- int slen;
- assert (pstr != NULL);
- if (DynExpand(pstr, slen = strlen(src))) {
- strcpy (DynValue(pstr), src);
- DB(pstr)->Length = slen;
- return TRUE;
- } /* if */
- return FALSE;
- } /* DynSCpy */
-
-
- Prototype BOOL DynDSCpy (DSTR *pstr, DSTR *src);
- BOOL DynDSCpy (DSTR *pstr, DSTR *src) {
- int slen;
- assert (pstr != NULL);
- if (DynExpand(pstr, slen = DynLen(src))) {
- strcpy (DynValue(pstr), DynValue(src));
- DB(pstr)->Length = slen;
- return TRUE;
- } /* if */
- return FALSE;
- } /* DynDSCpy */
-
-
- /* ---- Replace some chars within a DSTR */
- Prototype BOOL DynReplace (DSTR *pstr, const char *src, int pos, int chars);
- BOOL DynReplace (DSTR *pstr, const char *src, int pos, int chars) {
- int slen;
- slen = src? strlen(src): 0;
- assert (pstr != NULL);
-
- /* ---- we cannot write behind the end */
- if (pos > DynLen(pstr))
- return FALSE;
-
- /* ---- adjust the removed chars */
- if (pos + chars > DynLen(pstr))
- chars = DynLen(pstr) - pos;
-
- /* ---- expand the string */
- if (DynExpand(pstr, DynLen(pstr) + slen - chars)) {
-
- /* ---- make room for the replace part */
- if (slen != chars);
- memmove(DynValue(pstr) + pos + slen, DynValue(pstr) + pos + chars, 1 + DynLen(pstr) - (pos + chars));
-
- /* ---- insert the replace part */
- memmove(DynValue(pstr) + pos, src, slen);
- DB(pstr)->Length += slen - chars;
- return TRUE;
- } /* if */
- return FALSE;
- } /* DynReplace */
-
-
- /* ---- read all incoming data from a stream and insert it into a DSTR */
- Prototype BOOL DynGIns (DSTR *pstr, int pos, STREAM instream, char *(read)(STREAM));
- BOOL DynGIns (DSTR *pstr, int pos, STREAM instream, char *(read)(STREAM)) {
- char *data;
- assert (pstr != NULL);
-
- /* ---- I do not think that function needs any explanation */
- while (data = (*read)(instream)) {
- int olen = DynLen(pstr);
-
- if (!DynIns(pstr, data, pos))
- return FALSE;
-
- pos += DynLen(pstr) - olen;
- } /* while */
-
- return TRUE;
- } /* DynGIns */
-
-
- /* ---- Append several strings at one time ... */
- Prototype BOOL vDynAppend (DSTR *pstr, int num, va_list adds);
- BOOL vDynAppend (DSTR *pstr, int num, va_list adds) {
- int il;
- char* istr;
- assert (pstr != NULL);
-
- /* ---- append all adds to pstr */
- while (num-- > 0) {
- istr = va_arg(adds, char*);
-
- /* ---- ignore empty strings */
- if (!istr)
- continue;
-
- /* ---- make sure we have enough mem */
- il = strlen (istr);
-
- if (DynExpand(pstr, il + DynLen(pstr)))
- return FALSE;
-
- /* ---- append the string */
- strcpy (DynValue(pstr) + DynLen(pstr), istr);
- DB(pstr)->Length += il;
- } /* while */
-
- return TRUE;
- } /* vDynAppend */
-
-
- /* ---- Append a single char to a DSTR */
- /* Not the fastest way, but it should work */
- Prototype int DynPutc (DSTR *pstr, int c);
- int DynPutc (DSTR *pstr, int c) {
- unsigned char bf[2] = { 0, '\0' };
-
- bf[0] = c & 255;
- return DynCat(pstr, bf);
- } /* DynPutc */
-
-
- #ifdef AMIGA
-
- #if defined(__SASC)
- #define PREFIX __asm
- #define __D0(x) register __d0 x
- #define __A3(x) register __a3 x
- #elif defined(_DCC)
- #define PREFIX
- #define __D0(x) __D0 x
- #define __A3(x) __A3 x
- #endif
-
- /* ---- Not the fastest way, but it should work */
- static PREFIX int _DynPutc (__A3( DSTR *pstr ), __D0( int c )) {
- unsigned char bf[2] = { 0, '\0' };
-
- bf[0] = c & 255;
- return DynCat(pstr, bf);
- } /* DynPutc */
-
- /* ---- That function is _NOT_PORTABLE_! nor it can test, */
- /* if the operation ended successfully. */
- /* btw. remember - we have Flexprintf ;-) */
- Prototype BOOL vDynPrintf (DSTR *pstr, const char *tplt, va_list args);
- BOOL vDynPrintf (DSTR *pstr, const char *tplt, va_list args) {
- assert (pstr != NULL);
- RawDoFmt ((void *)tplt, args, (void *)_DynPutc, pstr);
- return TRUE;
- } /* vDynPrintf */
-
- #else
-
- /* no amiga? poor guy... */
- /* ---- Keep on Dreamin' 8-) ... btw. we have Flexprintf ;-) */
- /* Since there is no standardized way to access the format */
- /* function used by the *printf-funcs, and since I don't */
- /* want to reinvent the wheel, so.else may write that func */
- /* BOOL vDynPrintf (DSTR *pstr, const char *tplt, va_list args) {
- } /* vDynPrintf */
-
- #endif
-
- /* ---- strip all ending spaces */
- Prototype BOOL DynStripES (DSTR *pstr);
- BOOL DynStripES (DSTR *pstr) {
- int i;
- char *str;
- assert (pstr != NULL);
-
- /* ---- init */
- if (!(i = DynLen(pstr)))
- return FALSE;
- str = DynValue(pstr);
- --i;
-
- /* ---- remove all ending spaces */
- while ((i >= 0) && (str[i] < 33))
- str[i--] = 0;
-
- /* ---- restore the consistency */
- if (i < 0) {
- DynClear(pstr);
- return TRUE;
- } else if (DynLen(pstr) > i + 1) {
- DB(pstr)->Length = i + 1;
- return TRUE;
- } else
- return FALSE;
- } /* DynStripES */
-
- Prototype BOOL DynGetFile (DSTR *pstr, const char *name);
- BOOL DynGetFile (DSTR *pstr, const char *name) {
- FILE *fi;
- if ((fi = fopen (name, "r"))) {
- int size;
- fseek(fi, 0, SEEK_END);
- if (!DynExpand(pstr, 1 + (size = ftell(fi)))) {
- fclose (fi);
- return FALSE;
- } /* if */
- fseek(fi, 0, SEEK_SET);
-
- fread (DynValue(pstr), 1, size, fi);
- DynValue(pstr)[size] = 0;
-
- fclose(fi);
- return TRUE;
- } /* if */
- return FALSE;
- } /* DynGetFile */
-
-
- /******************************************************************************
- ***** END DYN.c
- ******************************************************************************/
-
-